#!/usr/bin/env python

#author:zhenghb@act.buaa.edu.cn
import sys
import os

from xml.dom import minidom
from urllib import urlretrieve
#from urlExists import httpExists
import httplib, urlparse 

from ivic.core import Logging
from ivic.vprocess.Config import  *

logger = Logging.get_logger('ivic.vprocess.XmlParse')
          
class Soft(object):

    def __init__(self, root):
        self.name = self.getSoftName(root)
        self.version = self.getSoftVersion(root)
        self.description = self.getSoftDescription(root)
        self.exec_cmd = self.getExec_Cmd(root)
        self.libfiles = self.getLibFiles(root)
        self.ldd_lib_dict = {}
        self.other_lib_dict = {}
        self.handleLddLibFiles(self.libfiles)
        self.handleOtherLibFiles(self.libfiles)
        
    def getText(self, nodelist):
        """get the content of a text node"""
        
        rc = ""
        for node in nodelist:
            if node.nodeType == node.TEXT_NODE:
                rc = rc + node.data
            return  rc
        
    def getExec_Cmd(self, root):
        """get execute command of soft""" 
        exec_cmd = root.getElementsByTagName("exec_cmd")[0]
        exec_cmd = self.getText(exec_cmd.childNodes).strip()
    
        return exec_cmd
    
    def getSoftName(self, root):
        """get soft name"""
        softname = root.getElementsByTagName("softname")[0]
        softname = self.getText(softname.childNodes).strip()
        
        return softname
    
    def getSoftDescription(self, root):
        """get soft description"""
        soft_description = root.getElementsByTagName("description")[0]
        soft_description = self.getText(soft_description.childNodes).strip()
        
        return soft_description
    
    def getSoftVersion(self, root):
        """get soft version"""
        soft_version = root.getElementsByTagName("version")[0]
        soft_description = self.getText(soft_version.childNodes).strip()
        
        return soft_description
    
    def getLibFiles(self, root):
        """get all libfile node in xml"""
        
        library = root.getElementsByTagName("library")[0]
        libfiles = library.getElementsByTagName("libfile")
        return libfiles
    
    def handleLddLibFiles(self, libfiles):
        """handle libfiles"""
        
        for libfile in libfiles:
            self.handleLddLibFile(libfile)
    
    def handleLddLibFile(self, libfile):
        """handle libfile, gets soname of dynamic files"""
        
        name = libfile.getAttribute("name")
        soname = libfile.getAttribute("soname")
        
        if libfile.getAttribute("ldd") == 'true':
            self.ldd_lib_dict[name] = soname
    
    def handleOtherLibFiles(self, libfiles):
        """handle othrer libfiles"""
        for libfile in libfiles:
            self.handleOtherLibFile(libfile)
    
    def handleOtherLibFile(self, libfile):
        """handle other libfile, gets soname of dynamic files"""
        
        name = libfile.getAttribute("name")
        soname = libfile.getAttribute("soname")
        
        if libfile.getAttribute("ldd") == 'false':
            self.other_lib_dict[name] = soname
            
def httpExists(url):  
    host, path = urlparse.urlsplit(url)[1:3]  
    if ':' in host:  
        #port specified, try to use it  
        host, port = host.split(':', 1)  
        try:  
            port = int(port)  
        except ValueError:  
            print  'invalid port number %r' % (port,)  
            return   False  
    else:  
        #no port specified, use default port  
        port = None  
    try:  
        connection = httplib.HTTPConnection(host, port=port)  
        connection.request("HEAD", path)  
        resp = connection.getresponse()  
        if  resp.status == 200: #normal 'found' status  
            found = True  
        elif resp.status == 302:#recurse on temporary redirect  
            found = httpExists(urlparse.urljoin(url, resp.getheader('location', '')))  
        else:#everything else -> not found  
            print "Status %d %s : %s" % (resp.status, resp.reason, url)  
            found = False  
    except Exception, e:  
        print e.__class__, e, url  
        found = False  
    return found  

def download(soft, config=None):
    """download the file from http://dev.ivic.org.cn/samba/ivic/incoming """
    if config == None:
        config = VProcessConfig()
        
    dst = '/'.join([config.transfer.warehouse, soft.name, 'usr/lib/'])
#    url = 'http://dev.ivic.org.cn/samba/ivic/incoming/appv/' + dst
#    print "url = %s" %url
#    
#    path = '/'.join(['/tmp/download',dst])
#    print "path = %s" %path
    
    cmd = "mkdir -pv " + dst
#    print cmd
    if not os.path.exists(dst):
        os.system(cmd)
    
    urlprefix = '/'.join([config.transfer.urlprefix, soft.name, 'usr/lib/'])
    ldd_lib_dict = soft.ldd_lib_dict
    
    for libfile in ldd_lib_dict.keys():
        libsoname = ldd_lib_dict[libfile]
        
        try:
            if os.path.exists(dst + libfile): continue 
            #enforce a new build, the previous build get error.?
            if os.path.exists("/usr/lib/" + libfile):
                #logger.debug("[EXIST]:%s "%("/usr/lib/" + libfile))
                continue
            urlretrieve(urlprefix + libfile, dst + libfile)
            os.chmod(dst + libfile, 0777)
#            #for logging use.
#            predownlib = dst + libfile
#            libinfo = os.lstat(predownlib)
            #logger.debug("[DOWNLOAD]:%s" % (dst + libfile))
        except:
            continue  
            
        try:
            if not os.path.exists(dst + libsoname):
                os.symlink(dst + libfile, dst + libsoname)
                #print 'download %s and create symlink %s' %(libfile,libsoname)
                os.chmod(dst + libsoname, 0777) 
        except OSError, e:
            print e
            pass

def main(software, config=None):
    if config == None:
        config = VProcessConfig()
        
#    url = "http://dev.ivic.org.cn/samba/ivic/incoming/appv"
    metaprefix = config.transfer.metaFile
    try:
        if not os.path.exists(config.transfer.warehouse):
            os.makedirs(config.transfer.warehouse, 0777)
            
        softxml = ''.join([software, ".xml"])
        dst = '/'.join([config.transfer.warehouse, softxml])
        url = '/'.join([metaprefix, softxml]) 
        
        if not os.path.exists(dst): 
            if httpExists(url) == False:
                print "%s is not exists" % url
                return False
            urlretrieve(url, dst)       

    except IndexError, e:
        print "sys.argv[1] %s" % e
        print '<usage>classxmlparse.py software' 
        return False
    
    except ContentTooShortError, e:
        print "download error, %s" % e
        return False
        
    dom = minidom.parse(dst)
    root = dom.documentElement
    soft = Soft(root)

    print "%s info" % soft.name
    print " softname = %s\n softdescription = %s\n soft_exec_cmd = %s\n softversion = %s\n" % (soft.name, soft.description, soft.exec_cmd, soft.version)
    
    print "ldd_lib_file"
    for libfile in soft.ldd_lib_dict.keys():
        print "  libfile = %s  soname = %s" % (libfile, soft.ldd_lib_dict[libfile])
    
    print "\nother_lib_file"
    for libfile in soft.other_lib_dict.keys():
        print "  libfile = %s  soname = %s" % (libfile, soft.other_lib_dict[libfile])
    
    download(soft, config)
    return soft

if __name__ == "__main__":
    main(sys.argv[1])
